<?php
/**
 * (logic)
 */
namespace App\Logic\MonthlyReportCommon;

use App\Models\Basics\SysCountry;
use App\Models\Basics\SysICountry;
use App\Models\Inventory\Record;
use App\Models\Inventory\StorageDetail;
use App\Models\Product\ProductAmazonSku;
use App\Models\Product\ProductSku;
use App\Models\MonthlyReport\Cost\OrderBasics;
use App\Models\MonthlyReportCommon\Cost\PriceBalance;
use App\Models\MonthlyReportCommon\Cost\PriceBasics;
use App\Models\MonthlyReportCommon\Cost\PriceRecord;
use App\Models\MonthlyReport\Tmp\TmpPSales;
use App\Models\MonthlyReportLT\Tmp\TmpSales;
use Illuminate\Support\Facades\DB;
class CheckPurPrice
{
    public static function exe($func){
        $time = strtotime('midnight first day of -1 month');
        try{
            DB::beginTransaction();
            self::{$func}($time);
            DB::commit();
        }catch (\Exception $e){
            DB::rollBack();
            report($e);
        }
    }

    /**
     * 5更新单价为0的产品(取默认单价)
     * @param $time
     */
    private static function _upSkuPriceBasics($time){
        $date = date('Y-m-01',$time);
        $ps = PriceBasics::query()
            ->where('b_date',$date)
            ->where('price',0)
            ->get();
        foreach ($ps as $_ps){
            $mix = PriceBalance::query()
                ->where('psku_id',$_ps->psku_id)
                ->orderBy('storage_at','DESC')
                ->first();
            if($mix){
                $_ps->price = $mix->b_price;
                $_ps->save();
            }else{
                $p = ProductSku::find($_ps->psku_id);
                if(!$p)continue;
                $_ps->price = ProductSku::getPuPrice($p);
                $_ps->save();
            }
        }
    }

    /**
     * 4订单sku价格
     * @param $time
     */
    private static function _mixSkuPriceBasics($time){
        $date = date('Y-m-01',$time);
        $end = date('Y-m-t',$time);
        $lines = OrderBasics::query()
            ->selectRaw('psku_id,sum(quantity) as quantity')
            ->where('b_date',$date)
            ->where('psku_id','<>',0)
            ->groupBy('psku_id')
            ->get();
        $i = 0;
        $num = 200;
        while(true){
            if($lines->isEmpty())break;
            $_lines = $lines->splice($i,$num);
            foreach ($_lines as $line){
                if($line->quantity == 0)continue;
                $mix = PriceBalance::query()
                    ->where('psku_id',$line->psku_id)
                    ->where('b_balance_sale','>',0)
                    ->orderBy('storage_at','ASC')
                    ->get();
                if($mix->isEmpty()){
                    $needDis = $line->quantity;
                    $storageDetail = StorageDetail::query()
                        ->whereHas('storage',function ($q) use ($end){
                            $q->where('type',1)->where('storage_at','<=',$end);
                        })
                        ->where('psku_id',$line->psku_id)
                        ->orderBy('id','DESC')
                        ->first();
                    if(!$storageDetail){
                        $ps = ProductSku::query()->find($line->psku_id);
                        $price = ProductSku::getPuPrice($ps);
                    }else{
                        $price = ($storageDetail->unit_price_no_tax ?: 0) + ($storageDetail->pack_price ?: 0);
                    }
                    $sum = $price * $needDis;
                }else{
                    $needDis = $line->quantity;
                    $lastPrice = 0;
                    $sum = 0;
                    foreach($mix as $_mix){
                        if($needDis == 0)break;
                        $min = min($needDis,$_mix->b_balance_sale);
                        $needDis -= $min;
                        $_mix->b_balance_sale -= $min;
                        $_mix->save();
                        PriceRecord::create([
                            'psku_id' => $line->psku_id,
                            'storage_at' => $_mix->storage_at,
                            'b_num' => $min,
                            'b_balance' => $_mix->b_balance_sale,
                        ]);
                        $lastPrice = $_mix->b_price ?: 0;
                        $sum += $min * $lastPrice;
                    }
                    if($needDis > 0){
                        $sum += $needDis * $lastPrice;
                    }
                }
                $price = round($sum / $line->quantity,3);
                PriceBasics::create(['b_date' => $date,
                    'psku_id' => $line->psku_id,
                    'quantity' => $line->quantity,
                    'price' => $price]);
            }
        }
    }

    /**
     * TODO  乐天
     * 3.2.乐天订单数据
     * @param $time
     */
//    private static function _mixOrderBasicsLT($time){
//        ini_set('memory_limit', '200M');
//        set_time_limit(0);
//        $date = date('Y-m-01',$time);
//        $lines = TmpSales::query()
//            ->selectRaw('sku,sum(quantity) as quantity')
//            ->where('report_date',$date)
//            ->whereNotNull('sku')
//            ->groupBy('sku')
//            ->get();
//        $i = 0;
//        $num = 500;
//        $has = [];
//        while(true){
//            if($lines->isEmpty())break;
//            $_lines = $lines->splice($i,$num);
//            foreach ($_lines as $line){
//                if(!array_key_exists($line->sku,$has)){
//                    $pas = ProductAmazonSku::query()
//                        ->where('seller_sku',$line->sku)
//                        ->first();
//                    $has[$line->sku] = $pas->psku_id ?? 0;
//                }
//                OrderBasicsLT::create(['b_date' => $date,
//                    'country_id' => 12,
//                    'seller_sku' => $line->sku,
//                    'quantity' => $line->quantity,
//                    'area_id' => 6,
//                    'psku_id' => $has[$line->sku]]);
//            }
//        }
//    }

    /**
     * 3.1.亚马逊订单数据
     * @param $time
     */
    private static function _mixOrderBasics($time){
        ini_set('memory_limit', '200M');
        set_time_limit(0);
        $date = date('Y-m-01',$time);
        $lines = TmpPSales::query()
            ->selectRaw('country,sku,sum(quantity) as quantity')
            ->where('report_date',$date)
            ->whereIn('type',['Order','Liquidations','Liquidations Adjustments'])
            ->whereNotNull('sku')
            ->groupBy(['country','sku'])
            ->get();
        $i = 0;
        $num = 500;
        $has = [];
        $country = [];
        $area = [];
        while(true){
            if($lines->isEmpty())break;
            $_lines = $lines->splice($i,$num);
            foreach ($_lines as $line){
                if(!$line->quantity)continue;
                if(!array_key_exists($line->country,$country)){
                    $_countryId = SysCountry::getIdByCountry($line->country);
                    $country[$line->country] = $_countryId ?: 0;
                }
                $countryId = $country[$line->country];
                if(!array_key_exists($countryId,$area)){
                    $area[$countryId] = SysICountry::getAreaIdByCountryId($countryId);
                }
                $areaId = $area[$countryId];
                if(!array_key_exists($line->sku,$has)){
                    $pas = ProductAmazonSku::query()
                        ->where('seller_sku',$line->sku)
                        ->first();
                    $has[$line->sku] = $pas->psku_id ?? 0;
                }
                OrderBasics::create(['b_date' => $date,
                    'country_id' => $countryId,
                    'seller_sku' => $line->sku,
                    'quantity' => $line->quantity,
                    'area_id' => $areaId,
                    'psku_id' => $has[$line->sku]]);
            }
        }
    }

    /**
     * 2 组合价格
     * @param $time
     */
    private static function _mixRecord($time){
        $start = date('Y-m-01 00:00:00',$time);
        $end = date('Y-m-t 23:59:59',$time);
        $recordNos = Record::query()
            ->where('created_at','>=',$start)
            ->where('created_at','<=',$end)
            ->where('action_type',2)
            ->where('num','<>',0)
            ->groupBy('record_no')
            ->orderBy('record_no')
            ->pluck('record_no');
        foreach($recordNos as $recordNo){
            //核算组合价格
            $records = Record::query()
                ->where('record_no',$recordNo)
                ->where('record_type',2)
                ->get();//出库
            $sum = 0;
            foreach($records as $record){
                $mix = PriceBalance::query()
                    ->where('psku_id',$record->psku_id)
                    ->where('b_balance_sale','>',0)
                    ->orderBy('storage_at','ASC')
                    ->get();
                if($mix->isEmpty()){
                    $needDis = abs($record->num);
                    $storageDetail = StorageDetail::query()
                        ->where('created_at','<=',$record->created_at)
                        ->where('psku_id',$record->psku_id)
                        ->orderBy('id','DESC')
                        ->first();
                    if(!$storageDetail){
                        $ps = ProductSku::query()->find($record->psku_id);
                        $price = ProductSku::getPuPrice($ps);
                    }else{
                        $price = ($storageDetail->unit_price_no_tax ?: 0) + ($storageDetail->pack_price ?: 0);
                    }
                    $_sum = $price * $needDis;
                }else{
                    $_sum = 0;
                    $needDis = abs($record->num);
                    $lastPrice = 0;
                    foreach($mix as $_mix){
                        if($needDis == 0)break;
                        $min = min($needDis,$_mix->b_balance_sale);
                        $needDis -= $min;
                        $_mix->b_balance_sale -= $min;
                        $_mix->save();
                        PriceRecord::create([
                            'psku_id' => $record->psku_id,
                            'storage_at' => $_mix->storage_at,
                            'b_num' => $min,
                            'b_balance' => $_mix->b_balance_sale,
                        ]);
                        $lastPrice = $_mix->b_price ?: 0;
                        $_sum += $min * $lastPrice;
                    }
                    if($needDis > 0){
                        $_sum += $needDis * $lastPrice;
                    }
                }
                $sum += $_sum;
            }
            $recordsIn = Record::query()
                ->where('record_no',$recordNo)
                ->where('record_type',1)
                ->first();
            $priceIn = round($sum / $recordsIn->num,3);
            $count = PriceBalance::query()
                ->where('psku_id',$recordsIn->psku_id)
                ->where('storage_at',$recordsIn->created_at)
                ->count();
            $createAt = $count > 0 ? date('Y-m-d H:i:s',(strtotime($recordsIn->created_at) + 1)) : $recordsIn->created_at;
            PriceBalance::create([
                'psku_id' => $recordsIn->psku_id,
                'b_num' => $recordsIn->num,
                'b_price' => $priceIn,
                'b_balance_sale' => $recordsIn->num,
                'storage_at' => $createAt,
            ]);
        }
    }

    /**
     * 1 收货入库价格
     * @param $time
     */
    private static function _exePurchaseStorage($time){
        $start = date('Y-m-01',$time);
        $end = date('Y-m-t',$time);
        StorageDetail::query()
            ->whereHas('storage',function ($q) use ($start,$end){
                $q->where('type',1)
                    ->where('storage_at','>=',$start)
                    ->where('storage_at','<=',$end);
            })
            ->orderBy('id','ASC')
            ->chunk(200, function ($items){
                foreach($items as $item){
                    if($item->storage_num < 0){
                        $_items = PriceBalance::query()
                            ->where('psku_id',$item->psku_id)
                            ->where('b_balance_sale','>',0)
                            ->orderBy('storage_at','DESC')
                            ->get();
                        $_tempNum = abs($item->storage_num);
                        foreach ($_items as $_item){
                            $min = min($_tempNum,$_item->b_balance_sale);
                            $_item->b_balance_sale -= $min;
                            $_tempNum -= $min;
                            $_item->save();
                            PriceRecord::create([
                                'psku_id' => $_item->psku_id,
                                'storage_at' => $_item->storage_at,
                                'b_num' => $min,
                                'b_balance' => $_item->b_balance_sale,
                            ]);
                            if($_tempNum == 0)break;
                        }
                    }else{
                        $count = PriceBalance::query()
                            ->where('psku_id',$item->psku_id)
                            ->where('storage_at',$item->created_at)
                            ->count();
                        $createAt = $count > 0 ? date('Y-m-d H:i:s',(strtotime($item->created_at) + 1)) : $item->created_at;
                        PriceBalance::create([
                            'psku_id' => $item->psku_id,
                            'b_num' => $item->storage_num,
                            'b_price' => ($item->unit_price_no_tax ?: 0) + ($item->pack_price ?: 0),
                            'b_balance_sale' => $item->storage_num,
                            'storage_at' => $createAt,
                        ]);
                    }
                }
            });
    }
}
